package com.fau.om.aop;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import com.fau.om.dao.IBaseDao;
import com.fau.om.entity.MedicalAdmin;
import com.fau.om.entity.MedicalMediaInfo;
import com.fau.om.entity.MedicalMediaInfoCosts;
import com.fau.om.entity.MedicalOrders;
import com.fau.om.entity.MedicalOrdersCheckSta;
import com.fau.om.entity.MedicalOrdersLog;
import com.fau.om.entity.MedicalOrdersMediaSta;
import com.fau.om.entity.MedicalOrdersPass;
import com.fau.om.entity.MedicalOrdersProduct;
import com.fau.om.entity.MedicalOrdersProvinceSta;
import com.fau.om.entity.MedicalOrdersRidepinSta;
import com.fau.om.entity.MedicalOrdersStorage;
import com.fau.om.util.SystemConfig;

/**
 * @desc 订单系统统计切面
 * @author dangjh
 * @datetime 2014年11月7日,上午10:37:45
 */
@Aspect
@Component
public class StatisticsAop {
	
	@Resource
	private IBaseDao iBaseDao;
	
	/**
	 * @desc 审核通过切点
	 * @author dangjh
	 * @datetime 2014年12月11日 下午9:22:04
	 */
	@Pointcut("execution(* com.fau.om.service.impl.AuditManagerService.auditOrdersPass(..))")
	private void auditOrdersPass() {}
	
	/**
	 * @desc 审核未通过切点
	 * @author dangjh
	 * @datetime 2014年12月11日 下午9:22:04
	 */
	@Pointcut("execution(* com.fau.om.service.impl.AuditManagerService.auditOrdersNoPass(..))")
	private void auditOrdersNoPass() {}
	
	/**
	 * @desc 取消订单切点
	 * @author dangjh
	 * @datetime 2014年12月12日 下午9:44:52
	 */
	@Pointcut("execution(* com.fau.om.service.impl.MaintainManagerService.cancelOrders(..))")
	private void cancelOrders() {}
	
	/**
	 * @desc 审核通过
	 * @param joinPoint
	 * @author dangjh
	 * @datetime 2014年12月12日 下午9:29:38
	 */
	@SuppressWarnings("unchecked")
	@AfterReturning("auditOrdersPass()")
	public void auditOrdersPass(JoinPoint joinPoint) {
		Object[] obj = joinPoint.getArgs();
		MedicalOrders orders = (MedicalOrders) obj[1];
		orders = (MedicalOrders) this.iBaseDao.getObjectByHql("from MedicalOrders m where m.id = ? ", orders.getId());
		if(null != orders) {
			MedicalOrdersCheckSta ordersCheck = new MedicalOrdersCheckSta();
			MedicalAdmin admin = null;
			if(StringUtils.isBlank(orders.getCheckUserId())) {
				admin = (MedicalAdmin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			} else {
				admin = (MedicalAdmin) this.iBaseDao.getObject(MedicalAdmin.class, orders.getCheckUserId());
			}
			
			// 记录订单操作日志
			MedicalOrdersLog log = new MedicalOrdersLog();
			log.setOrderNo(orders.getSerialNum());
			log.setName(admin.getName());
			log.setUserName(admin.getUsername());
			log.setContent("订单审核操作  订单审核通过");
			log.setEid(admin.getEnterpriseId());
			this.iBaseDao.saveObject(log);
			
			ordersCheck.setCheckUserId(admin.getId());
			ordersCheck.setCheckUserName(admin.getName());
			ordersCheck.setCheckType(SystemConfig.ORDERS_AUDIT_PASS_TYPE);
			ordersCheck.setCheckTime(new Date());
			ordersCheck.setHospitalId(orders.getHospitalId());
			this.iBaseDao.saveObject(ordersCheck);
			
			//---------------------------媒体订单统计---------------------------
			this.saveMediaOrders(orders);
			//---------------------------各省订单统计---------------------------
			this.saveProvinceSta(orders);
			//---------------------------订单搭销产品统计---------------------------
			this.saveRidePin(orders);
			
			//---------------------------媒体系统-媒体进线成本统计----------------
			List<MedicalOrdersProduct> list = this.iBaseDao.getBySql("from MedicalOrdersProduct m where m.ordersId = ? ", null, orders.getId());
			for(MedicalOrdersProduct product : list) {
				List<MedicalMediaInfoCosts> mediaList = this.iBaseDao.getBySql("from MedicalMediaInfoCosts m where m.mediaId = ? and "
						+ "m.medicineId = ? order by m.createTime desc ", null, orders.getMedia().getId(), product.getId());
				if(null != mediaList && mediaList.size() > 0) {
					MedicalMediaInfoCosts cost = mediaList.get(0);
					// 查询媒体投放信息对应的日进线数量
					int inNum = this.iBaseDao.getIntCount("select count(distinct m.callerNum) from MedicalCallCaller m where m.outsideNum = ? "
							+ " and m.callerTime >= ? ", cost.getPublishNumbers(), cost.getPutTime());
					cost.setInNum(inNum);
					// 计算日进线成本
					double dailyCost = cost.getCosts().doubleValue() / inNum;
					cost.setDailyCost(new BigDecimal(dailyCost));
					cost.setOrderNum(cost.getOrderNum()+1);
					// 有效单成本 = 有效单金额 / 进线数量    
					BigDecimal orderCost = orders.getPayment().add(orders.getFreight());
					double ordercost = orderCost.doubleValue() / inNum;
					cost.setEffectiveCost(new BigDecimal(ordercost));
					this.iBaseDao.saveObject(cost);
				}
			}
		}
	}
	
	/**
	 * @desc 保存媒体统计订单信息
	 * @author dangjh
	 * @datetime 2014年12月13日 下午6:14:48
	 */
	private void saveMediaOrders(MedicalOrders ordersPass) {
		MedicalOrdersMediaSta mediaSta = new MedicalOrdersMediaSta();
		mediaSta.setOrdersId(ordersPass.getId());
		mediaSta.setMediaId(ordersPass.getMedia().getId());
		MedicalMediaInfo info = (MedicalMediaInfo) this.iBaseDao.getObjectByHql("from MedicalMediaInfo m where m.id = ? ", ordersPass.getMedia().getId());
		if(null != info) {
			mediaSta.setMediaName(info.getName());
		}
		mediaSta.setCommodityMoney(ordersPass.getPayment());
		mediaSta.setFreight(ordersPass.getFreight());
		int count = this.iBaseDao.getIntCount("select count(*) from MedicalOrdersProduct m where m.ordersId = ? and m.medicine.medicineType = ? ", ordersPass.getId(), SystemConfig.MEDICINE_RIDEPIN_TYPE);
		if(count > 0) {
			mediaSta.setRidePin(SystemConfig.RIDEPIN_ORDERS_TYPE);	// 搭销订单
		} else {
			mediaSta.setRidePin(SystemConfig.RIDEPIN_ORDERS_NO);	// 不是搭销订单
		}
		mediaSta.setOrdersTime(ordersPass.getCreateTime());
		mediaSta.setHospitalId(ordersPass.getHospitalId());
		this.iBaseDao.saveObject(mediaSta);
	}
	
	/**
	 * @desc 各省份订单统计
	 * @param ordersPass
	 * @author dangjh
	 * @datetime 2014年12月13日 下午8:48:18
	 */
	private void saveProvinceSta(MedicalOrders ordersPass) {
		MedicalOrdersProvinceSta order = new MedicalOrdersProvinceSta();
		order.setOrdersId(ordersPass.getId());
		order.setProvinceId(ordersPass.getProvince().getId());
		order.setProvinceName(ordersPass.getProvince().getpName());
		order.setCommodityMoney(ordersPass.getPayment());
		order.setDeliveryType(SystemConfig.ORDERS_WAIT_DELIVERY_TYPE);	// 审核通过后计入，待发货状态
		order.setHospitalId(ordersPass.getHospitalId());
		order.setOrdersTime(ordersPass.getCreateTime());
		this.iBaseDao.saveObject(order);
	}
	
	/**
	 * @desc 保存订单搭销产品统计信息
	 * @author dangjh
	 * @datetime 2014年12月13日 下午6:07:46
	 */
	@SuppressWarnings("unchecked")
	private void saveRidePin(MedicalOrders ordersPass) {
		MedicalOrdersRidepinSta ridepinSta = new MedicalOrdersRidepinSta();
		ridepinSta.setOrdersId(ordersPass.getId());
		ridepinSta.setOrdersNum(ordersPass.getSerialNum());
		ridepinSta.setOrdersTime(ordersPass.getCreateTime());
		List<MedicalOrdersProduct> list = this.iBaseDao.getBySql("from MedicalOrdersProduct m where m.ordersId = ? ", null, ordersPass.getId());
		StringBuilder productDetail = new StringBuilder();
		Integer totalProCount = 0;
		for(MedicalOrdersProduct pro : list) {
			if(SystemConfig.MEDICINE_PREMIUMS_TYPE.equals(pro.getMedicine().getMedicineType())) { // 略过赠品
				totalProCount = list.size() - 1;
				continue;
			} else {
				productDetail.append(pro.getMedicine().getName()+"+");
			}
		}
		if(StringUtils.isNotBlank(productDetail)) {
			productDetail.deleteCharAt(productDetail.lastIndexOf("+"));
			ridepinSta.setProductDetail(productDetail.toString());
			ridepinSta.setProductCount(totalProCount);
			
			// 主要产品数
			int mainProduct = this.iBaseDao.getIntCount("select count(*) from MedicalOrdersProduct m where m.ordersId = ? and m.medicine.medicineType = ? ", ordersPass.getId(), SystemConfig.MEDICINE_GENERAL_TYPE);
			// 搭销产品数
			int ridePinProduct = this.iBaseDao.getIntCount("select count(*) from MedicalOrdersProduct m where m.ordersId = ? and m.medicine.medicineType = ? ", ordersPass.getId(), SystemConfig.MEDICINE_RIDEPIN_TYPE);;
			ridepinSta.setMainProduct(mainProduct);
			ridepinSta.setRidePinProduct(ridePinProduct);
			ridepinSta.setMediaId(ordersPass.getMedia().getId());
			ridepinSta.setMediaName(ordersPass.getMedia().getName());
			ridepinSta.setHospitalId(ordersPass.getHospitalId());
			ridepinSta.setCusSerId(ordersPass.getCusSerId());
			this.iBaseDao.saveObject(ridepinSta);
		}
	}
	
	/**
	 * @desc 审核未通过
	 * @param joinPoint
	 * @author dangjh
	 * @datetime 2014年12月12日 下午9:29:38
	 */
	@AfterReturning("auditOrdersNoPass()")
	public void auditOrdersNoPass(JoinPoint joinPoint) {
		Object[] obj = joinPoint.getArgs();
		MedicalOrders orders = (MedicalOrders) obj[1];
		MedicalOrders ordersNoPass = (MedicalOrders) this.iBaseDao.getObjectByHql("from MedicalOrders m where m.id = ? ", orders.getId());
		if(null != ordersNoPass) {
			MedicalOrdersCheckSta ordersCheck = new MedicalOrdersCheckSta();
			MedicalAdmin admin = null;
			if(StringUtils.isBlank(orders.getCheckUserId())) {
				admin = (MedicalAdmin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			} else {
				admin = (MedicalAdmin) this.iBaseDao.getObject(MedicalAdmin.class, orders.getCheckUserId());
			}
			
			// 记录订单操作日志
			MedicalOrdersLog log = new MedicalOrdersLog();
			log.setOrderNo(ordersNoPass.getSerialNum());
			log.setName(admin.getName());
			log.setUserName(admin.getUsername());
			log.setContent("订单审核操作  订单审核不通过");
			log.setEid(admin.getEnterpriseId());
			this.iBaseDao.saveObject(log);
						
			ordersCheck.setCheckUserId(admin.getId());
			ordersCheck.setCheckUserName(admin.getName());
			ordersCheck.setCheckType(SystemConfig.ORDERS_AUDIT_NOPASS_TYPE);
			ordersCheck.setCheckTime(new Date());
			ordersCheck.setHospitalId(ordersNoPass.getHospitalId());
			this.iBaseDao.saveObject(ordersCheck);
		}
	}
	
	/**
	 * @desc 订单取消
	 * @param joinPoint
	 * @author dangjh
	 * @datetime 2014年12月12日 下午9:47:56
	 */
	@AfterReturning("cancelOrders()")
	public void cancelOrders(JoinPoint joinPoint) {
		Object[] obj = joinPoint.getArgs();
		MedicalOrdersPass ordersPass = (MedicalOrdersPass) obj[0];
		ordersPass = (MedicalOrdersPass) this.iBaseDao.getObjectByHql("from MedicalOrdersPass m where m.id = ? ", ordersPass.getId());
		if(null != ordersPass) {
			MedicalOrdersCheckSta ordersCheck = new MedicalOrdersCheckSta();
			MedicalAdmin admin = (MedicalAdmin) this.iBaseDao.getObject(MedicalAdmin.class, ordersPass.getCheckUserId());
			ordersCheck.setCheckUserId(admin.getId());
			ordersCheck.setCheckUserName(admin.getName());
			ordersCheck.setCheckType(SystemConfig.ORDERS_AUDIT_CANCEL_TYPE);
			ordersCheck.setCheckTime(new Date());
			ordersCheck.setHospitalId(ordersPass.getHospitalId());
			this.iBaseDao.saveObject(ordersCheck);
			
			// 记录订单操作日志
			MedicalOrdersLog log = new MedicalOrdersLog();
			log.setOrderNo(ordersPass.getSerialNum());
			log.setName(admin.getName());
			log.setUserName(admin.getUsername());
			log.setContent("订单取消操作  订单取消");
			log.setEid(admin.getEnterpriseId());
			this.iBaseDao.saveObject(log);
						
			// 删除 财务系统产品销售量统计
			this.iBaseDao.updateHql("delete from MedicalProductStorage m where m.orderId = ? ", ordersPass.getId());
			// 删除订单搭销产品
			this.iBaseDao.updateHql("delete from MedicalOrdersRidepinSta m where m.ordersId = ? ", ordersPass.getId());
			// 各省订单统计删除
			this.iBaseDao.updateHql("delete from MedicalOrdersProvinceSta m where m.ordersId = ? ", ordersPass.getId());
		}
	}
	
	/**
	 * @desc 订单失效
	 * @author dangjh
	 * @datetime 2014年12月12日 下午11:41:59
	 */
	@Pointcut("execution(* com.fau.om.service.impl.AuditManagerService.auditOrdersInvalid(..))")
	private void auditOrdersInvalid() {}
	
	/**
	 * @desc 删除失效订单
	 * @param joinPoint
	 * @author dangjh
	 * @datetime 2014年12月12日 下午11:55:27
	 */
	@AfterReturning("auditOrdersInvalid()")
	public void auditOrdersInvalid(JoinPoint joinPoint) {
		Object[] obj = joinPoint.getArgs();
		MedicalOrders order = (MedicalOrders) obj[0];
		
		MedicalAdmin admin = (MedicalAdmin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		MedicalOrdersStorage orders = (MedicalOrdersStorage) this.iBaseDao.getObject(MedicalOrdersStorage.class, order.getId());
		// 记录订单操作日志
		MedicalOrdersLog log = new MedicalOrdersLog();
		log.setOrderNo(orders.getSerialNum());
		log.setName(admin.getName());
		log.setUserName(admin.getUsername());
		log.setContent("订单审核操作  订单失效");
		log.setEid(admin.getEnterpriseId());
		this.iBaseDao.saveObject(log);
		
		// 核单员订单统计
		MedicalOrdersCheckSta ordersCheck = new MedicalOrdersCheckSta();
		MedicalAdmin checkUser = (MedicalAdmin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		ordersCheck.setCheckUserId(checkUser.getId());
		ordersCheck.setCheckUserName(checkUser.getName());
		ordersCheck.setCheckType(SystemConfig.ORDERS_AUDIT_INVALID_TYPE);
		ordersCheck.setCheckTime(new Date());
		ordersCheck.setHospitalId(orders.getHospitalId());
		this.iBaseDao.saveObject(ordersCheck);
		
		// 删除媒体订单统计数据
		this.iBaseDao.updateHql("delete from MedicalOrdersMediaSta m where m.ordersId = ? ", order.getId());
	}
	
}
